package edu.cmu.cs.stage3.alice.authoringtool.util;

import edu.cmu.cs.stage3.alice.authoringtool.AuthoringTool;
import edu.cmu.cs.stage3.alice.authoringtool.AuthoringToolResources;
import edu.cmu.cs.stage3.util.StringObjectPair;

public class CallToUserDefinedQuestionPrototype extends QuestionPrototype {

 protected edu.cmu.cs.stage3.alice.core.question.userdefined.UserDefinedQuestion actualQuestion;
 protected RefreshListener refreshListener = new RefreshListener();

 public CallToUserDefinedQuestionPrototype( edu.cmu.cs.stage3.alice.core.question.userdefined.UserDefinedQuestion actualQuestion ) {
  super( edu.cmu.cs.stage3.alice.core.question.userdefined.CallToUserDefinedQuestion.class, new StringObjectPair[0], new String[0] );
  this.actualQuestion = actualQuestion;

 }

 public void startListening() {
  if( actualQuestion != null ) {
   actualQuestion.requiredFormalParameters.addObjectArrayPropertyListener( refreshListener );
   Object[] vars = actualQuestion.requiredFormalParameters.getArrayValue();
   //LOB for (Object var : vars)
   int t_tam = vars!=null ? vars.length : 0;
   for (int i_i=0; i_i<t_tam; i_i++) {
    ((edu.cmu.cs.stage3.alice.core.Variable)vars[i_i]).name.addPropertyListener( refreshListener ); //L ((...)var)...
   }
  } else {
   AuthoringTool.getInstance().showErrorDialog( "actualQuestion is null", null );
  }
 }

 public void stopListening() {
  if( actualQuestion != null ) {
   actualQuestion.requiredFormalParameters.removeObjectArrayPropertyListener( refreshListener );
   Object[] vars = actualQuestion.requiredFormalParameters.getArrayValue();
   //LOB for (Object var : vars)
   int t_tam = vars!=null ? vars.length : 0;
   for (int i_i=0; i_i<t_tam; i_i++) {
    ((edu.cmu.cs.stage3.alice.core.Variable)vars[i_i]).name.removePropertyListener( refreshListener ); //L ((...)var)...
   }
  } else {
   AuthoringTool.getInstance().showErrorDialog( "actualQuestion is null", null );
  }
 }

 protected CallToUserDefinedQuestionPrototype( edu.cmu.cs.stage3.alice.core.question.userdefined.UserDefinedQuestion actualQuestion, StringObjectPair[] knownPropertyValues, String[] desiredProperties ) {
  super( edu.cmu.cs.stage3.alice.core.question.userdefined.CallToUserDefinedQuestion.class, knownPropertyValues, desiredProperties );
  this.actualQuestion = actualQuestion;
 }

 //Rem @Override
 public edu.cmu.cs.stage3.alice.core.Element createNewElement() {
  java.util.HashMap knownMap = new java.util.HashMap();
  //LOB for (StringObjectPair knownPropertyValue : knownPropertyValues)
  int t_tam = knownPropertyValues!=null ? knownPropertyValues.length : 0;
  for (int i_i=0; i_i<t_tam; i_i++) {
   knownMap.put( knownPropertyValues[i_i].getString(), knownPropertyValues[i_i].getObject() ); //L knownPropertyValue.getString(), knownPropertyValue.getObject()
  }

  edu.cmu.cs.stage3.alice.core.question.userdefined.CallToUserDefinedQuestion callToUserDefinedQuestion = new edu.cmu.cs.stage3.alice.core.question.userdefined.CallToUserDefinedQuestion();
  callToUserDefinedQuestion.userDefinedQuestion.set( actualQuestion );
  Object[] params = actualQuestion.requiredFormalParameters.getArrayValue();
  //LOB for (Object param : params)
  t_tam = params!=null ? params.length : 0;
  for (int i_i = 0; i_i < params.length; i_i++) {
   edu.cmu.cs.stage3.alice.core.Variable formalParameter = (edu.cmu.cs.stage3.alice.core.Variable)params[i_i]; //L (...)param;
   edu.cmu.cs.stage3.alice.core.Variable actualParameter = new edu.cmu.cs.stage3.alice.core.Variable();
   actualParameter.name.set( formalParameter.name.get() );
   actualParameter.valueClass.set( formalParameter.valueClass.get() );
   if (!knownMap.containsKey(formalParameter.name.get())){
    actualParameter.value.set( AuthoringToolResources.getDefaultValueForClass((Class)formalParameter.valueClass.get()) );
   } else{
    actualParameter.value.set( knownMap.get( formalParameter.name.get() ) );
   }
   callToUserDefinedQuestion.addChild( actualParameter );
   callToUserDefinedQuestion.requiredActualParameters.add( actualParameter );
  }

  return callToUserDefinedQuestion;
 }

 //Rem @Override
 public ElementPrototype createCopy( StringObjectPair[] newKnownPropertyValues ) {
  return super.createCopy( newKnownPropertyValues );
 }

 public edu.cmu.cs.stage3.alice.core.question.userdefined.UserDefinedQuestion getActualQuestion() {
  return actualQuestion;
 }

 private void calculateDesiredProperties() {
  Object[] params = actualQuestion.requiredFormalParameters.getArrayValue();
  desiredProperties = new String[params.length];
  for( int i = 0; i < params.length; i++ ) {
   desiredProperties[i] = ((edu.cmu.cs.stage3.alice.core.Variable)params[i]).name.getStringValue();
  }
 }

 // a rather inelegant solution for creating copies of the correct type.
 // subclasses should override this method and call their own constructor
 //Rem @Override
 protected ElementPrototype createInstance( Class elementClass, StringObjectPair[] knownPropertyValues, String[] desiredProperties ) {
  return new CallToUserDefinedQuestionPrototype( actualQuestion, knownPropertyValues, desiredProperties );
 }

 class RefreshListener implements edu.cmu.cs.stage3.alice.core.event.ObjectArrayPropertyListener, edu.cmu.cs.stage3.alice.core.event.PropertyListener {
  public void objectArrayPropertyChanging( edu.cmu.cs.stage3.alice.core.event.ObjectArrayPropertyEvent ev ) {}
  public void objectArrayPropertyChanged( edu.cmu.cs.stage3.alice.core.event.ObjectArrayPropertyEvent ev ) {
   try {
    if( ev.getChangeType() == edu.cmu.cs.stage3.alice.core.event.ObjectArrayPropertyEvent.ITEM_INSERTED ) {
     edu.cmu.cs.stage3.alice.core.Variable variable = (edu.cmu.cs.stage3.alice.core.Variable)ev.getItem();
     variable.name.addPropertyListener( this );
    } else if( ev.getChangeType() == edu.cmu.cs.stage3.alice.core.event.ObjectArrayPropertyEvent.ITEM_REMOVED ) {
     edu.cmu.cs.stage3.alice.core.Variable variable = (edu.cmu.cs.stage3.alice.core.Variable)ev.getItem();
     variable.name.removePropertyListener( this );
    }
   } catch( Throwable t ) {
    //BIG FAT HACK
   }
   calculateDesiredProperties();
  }
  public void propertyChanging( edu.cmu.cs.stage3.alice.core.event.PropertyEvent ev ) {}
  public void propertyChanged( edu.cmu.cs.stage3.alice.core.event.PropertyEvent ev ) {
   calculateDesiredProperties();
  }
 }

}

